package com.maoshi.shop.multishop.controller;


import com.alipay.api.AlipayApiException;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.maoshi.shop.bean.bo.RefundInfoBo;
import com.maoshi.shop.bean.dto.OrderRefundDto;
import com.maoshi.shop.bean.model.OrderRefund;
import com.maoshi.shop.bean.param.OrderRefundParam;
import com.maoshi.shop.common.annotation.SysLog;
import com.maoshi.shop.common.enums.PayType;
import com.maoshi.shop.common.enums.MaoshiHttpStatus;
import com.maoshi.shop.common.exception.MaoshiShopBindException;
import com.maoshi.shop.common.util.Json;
import com.maoshi.shop.common.util.PageParam;
import com.maoshi.shop.security.multishop.util.SecurityUtils;
import com.maoshi.shop.service.OrderRefundService;
import com.maoshi.shop.service.PayManagerService;
import lombok.AllArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@RestController
@AllArgsConstructor
@RequestMapping("/order/refund")
public class OrderRefundController {

    private final OrderRefundService orderRefundService;

    private final PayManagerService payManagerService;


    /**
     * 分页查询
     *
     * @param page           分页对象
     * @param orderRefundDto 实体对象
     * @return 分页数据
     */
    @GetMapping("/page")
    public ResponseEntity<IPage<OrderRefundDto>> getOrderRefundPage(PageParam<OrderRefundDto> page, OrderRefundDto orderRefundDto,
                                                                    @RequestParam(required = false) String startTime, @RequestParam(required = false) String endTime) {
        orderRefundDto.setShopId(SecurityUtils.getShopUser().getShopId());
        return ResponseEntity.ok(orderRefundService.getPage(page, orderRefundDto, startTime, endTime));
    }

    /**
     * 通过id查询
     *
     * @param refundId id
     * @return 查询详细信息
     */
    @GetMapping("/info/{refundId}")
    public ResponseEntity<OrderRefund> getById(@PathVariable("refundId") Long refundId) {
        OrderRefund orderRefund = orderRefundService.getOrderRefundById(refundId, SecurityUtils.getShopUser().getShopId());
        return ResponseEntity.ok(orderRefund);
    }

    /**
     * 进入这个方法，会出现两种情况：
     * 1. 仅退款，此时商家同意买家的退款申请，执行发放退款的操作
     * 2. 退货退款操作:
     *   2.1)退货退款的第一步，商家允许买家退款的申请，商家进行设置退货地址，不执行发放退款的操作
     *   2.2)退货退款的第二步，当商家收到货之后，同意买家退款，此时需要发放退款，但不会执行这个方法，执行的是下面这个方法
     *   @see com.maoshi.shop.multishop.controller.OrderRefundController#returnMoney(OrderRefundParam)
     *
     *
     */
    @SysLog("退款处理 -商家处理退款订单")
    @PutMapping("/process")
    public ResponseEntity<Void> processRefundOrder(@RequestBody OrderRefundParam orderRefundParam) {

        // 处理退款操作
        OrderRefundDto orderRefundDto = orderRefundService.processRefundOrder(orderRefundParam, SecurityUtils.getShopUser().getShopId());
        // 仅退款，执行退款操作
        if (Objects.equals(orderRefundDto.getApplyType(), 1)) {
            orderRefundService.submitWxRefund(orderRefundDto);
        }
        return ResponseEntity.ok().build();
    }

    /**
     * 退货处理
     */
    @SysLog("退款处理 -商家退货处理")
    @PutMapping("/returnMoney")
    public ResponseEntity<Void> returnMoney(@RequestBody OrderRefundParam orderRefundParam) {
        if (Objects.isNull(orderRefundParam.getIsReceiver())) {
            throw new MaoshiShopBindException("退货状态不能为空");
        }
        // 退货处理
        OrderRefundDto orderRefundDto = orderRefundService.returnMoney(orderRefundParam, SecurityUtils.getShopUser().getShopId());
        // 执行退款操作
        orderRefundService.submitWxRefund(orderRefundDto);
        return ResponseEntity.ok().build();
    }

    /**
     * 退款请求（发放退款）
     */
    @SysLog("退款处理-发放退款")
    @PutMapping("/refundRequest")
    public void refundRequest(@RequestBody String refundSn) {
        // 获取退款信息
        OrderRefundDto orderRefundDto = orderRefundService.getOrderRefundByRefundSn(refundSn);

        if (orderRefundDto == null) {
            throw new MaoshiShopBindException("退款单不存在");
        }

        if (orderRefundDto.getDecisionTime() == null) {
            throw new MaoshiShopBindException("请先确定退款，才能发起退款操作");
        }

        if (orderRefundDto.getRefundTime() != null) {
            throw new MaoshiShopBindException("已退款成功，无法再申请退款操作");
        }

        if (!Objects.equals(orderRefundDto.getShopId(), SecurityUtils.getShopUser().getShopId())) {
            throw new MaoshiShopBindException(MaoshiHttpStatus.UNAUTHORIZED);
        }
        // 提交退款请求
        orderRefundService.submitWxRefund(orderRefundDto);
    }

    /**
     * 退款结果通知
     */
    @RequestMapping("/result/{payType}")
    public String result(HttpServletRequest request, @RequestBody String xmlData, @PathVariable Integer payType) throws WxPayException, UnsupportedEncodingException, AlipayApiException {

        RefundInfoBo refundInfo = payManagerService.validateAndGetRefundInfo(request, PayType.instance(payType), xmlData);
        if (refundInfo.getIsRefundSuccess()) {
            // 查询退款订单，验证退款信息
            OrderRefundDto orderRefundDto = orderRefundService.getOrderRefundByRefundSn(refundInfo.getRefundNo());
            orderRefundService.verifyRefund(orderRefundDto, refundInfo.getBizRefundNo());
        }
        // 响应结果
        Map<String, String> result = new HashMap<>(16);
        result.put("return_code", "SUCCESS");
        result.put("return_msg", "OK");
        return Json.toJsonString(result);
    }

}
